<template>
  <div class="document-container">
    <div class="top-section">
      <div class="info-panel">
        <div class="panel-header">
          <div class="granary-header">
            <el-upload
              class="avatar-uploader"
              action="#"
              :show-file-list="false"
              :before-upload="beforeAvatarUpload"
              :http-request="handleAvatarUpload"
            >
              <img 
                v-if="granaryForm.avatar" 
                :src="granaryForm.avatar" 
                class="avatar" 
              />
              <img 
                v-else 
                src="@/assets/icon/granary.png" 
                class="avatar default-avatar" 
              />
            </el-upload>
            
            <div class="granary-title">
              <el-form :model="granaryForm">
                <el-form-item>
                  <el-input
                    v-model="granaryForm.name"
                    placeholder="给知识库起个名字吧"
                    class="name-input"
                  />
                </el-form-item>
              </el-form>
            </div>
          </div>
        </div>

        <el-form :model="granaryForm" class="form-content">
          <el-form-item label="描述：" class="full-width">
            <el-input
              v-model="granaryForm.description"
              placeholder="请输入知识库描述"
              type="textarea"
              :rows="2"
              class="description-input"
            />
          </el-form-item>

          <el-form-item label="摘要：" class="full-width">
            <el-input
              :model-value="granary?.summary || ''"
              type="textarea"
              :rows="2"
              readonly
              :placeholder="'暂无内容'"
              class="summary-input"
            />
          </el-form-item>

          <el-form-item label="关键词：" class="full-width">
            <div class="granary-tags">
              <span v-for="tag in granaryForm.tags" :key="tag" class="tag">{{ tag }}</span>
            </div>
          </el-form-item>

          <el-form-item label="构建状态：">
            <div class="status-container">
              <el-tag :type="formatGranaryStatus(granaryForm.currentGranay?.status).type">
                {{ formatGranaryStatus(granaryForm.currentGranay?.status).text }}
              </el-tag>
              <template v-if="canOperator()">
                <template v-if="isRunning">
                  <el-tooltip content="停止更新" placement="top">
                    <el-button 
                      class="control-btn stop-btn" 
                      plain 
                      @click="handleStop()"
                    >
                      <img 
                        :src="stopIcon" 
                        class="control-icon" 
                        alt="停止" 
                      />
                    </el-button>
                  </el-tooltip>
                </template>
                <template v-else>
                  <el-tooltip content="全量更新" placement="top">
                    <el-button 
                      class="control-btn start-btn" 
                      plain 
                      @click="handleStart()"
                    >
                      <img 
                        :src="startIcon" 
                        class="control-icon" 
                        alt="全量更新" 
                      />
                    </el-button>
                  </el-tooltip>
                  <el-tooltip content="增量更新" placement="top">
                    <el-button 
                      class="control-btn update-btn" 
                      plain 
                      @click="handleUpdate()"
                    >
                      <img 
                        src="@/assets/icon/update.png" 
                        class="control-icon" 
                        alt="增量更新" 
                      />
                    </el-button>
                  </el-tooltip>
                </template>
              </template>
            </div>
          </el-form-item>
          <el-form-item label="LLM模型：">
            <el-select v-model="granaryForm.llmModel" placeholder="请选择LLM模型" class="model-select">
              <el-option 
                v-for="model in llmModels" 
                :key="model.urn" 
                :label="model.name" 
                :value="model.urn"
              />
            </el-select>
          </el-form-item>

          <el-form-item label="Embed：">
            <el-select v-model="granaryForm.embeddingModel" placeholder="请选择Embedding模型" class="model-select">
              <el-option 
                v-for="model in embeddingModels" 
                :key="model.urn" 
                :label="model.name" 
                :value="model.urn"
              />
            </el-select>
          </el-form-item>

          <el-form-item label="构建类型：">
            <el-checkbox-group v-model="granaryForm.options">
              <el-checkbox 
                v-for="option in buildTypeOptions" 
                :key="option.value"
                :label="option.value"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>

          <div class="form-footer" v-if="canOperator()">
            <el-button type="primary" @click="saveGranary" class="primary-button">
              保存
            </el-button>
          </div>
        </el-form>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { useUserStore } from '@/store/user'
import { GetGranaryRequest,ListGranariesRequest,ListGranariesResponse, Granary } from '@/types/proto/api/v1/granary_service'
import { Resource, GetResourceRequest, CreateResourceRequest } from '@/types/proto/api/v1/resource_service'
import { ListResources, GetResource, CreateResource } from "@/api/resource";
import { GetGranary, CreateGranary, UpdateGranary, CtrlGranary } from "@/api/granary";
import { CreateGranaryRequest, UpdateGranaryRequest, CtrlGranaryRequest, GranaryCmd, GranaryStatus } from '@/types/proto/api/v1/granary_service'
import { ListModels } from "@/api/llm";
import { LLMModel,ListLLMModelResponse, ModelType } from '@/types/proto/api/v1/llm_service'
import { getBaseUrl } from '@/config'
import startIcon from '@/assets/icon/start.png'
import stopIcon from '@/assets/icon/stop.png'
import { formatGranaryStatus } from "@/api/granary";
const documents = ref<Resource[]>([])
const userStore = useUserStore()
const granary = ref<Granary | null>(null)
const llmModels = ref<LLMModel[]>([])
const embeddingModels = ref<LLMModel[]>([])
const isRunning = computed(() => {
  if (granary.value == null) {
    return false
  }
  switch (granary.value.status) {
          case GranaryStatus.CHUNKING:
          case GranaryStatus.STARTING:
          case GranaryStatus.GRAPHING:
          case GranaryStatus.SUMMARIZING:
          case GranaryStatus.STARTING:
            return true
          default:
            return false
        }
})

const isAdmin = computed(() => userStore.userInfo?.role === 'TENANT_ADMIN')
const canOperator = () =>{
  if(isAdmin.value){
    return true
  }

  if(granary.value?.creator?.id === userStore.userInfo?.id){
    return true
  }

  return false
}

const buildTypeOptions = [  
  { value: 'chunk', label: '分块'},
  { value: 'graph', label: '知识图谱' },
  { value: 'summary', label: '知识总结' }
]

interface GranaryForm {
  name: string
  description: string
  avatar: string
  avatarCache: string
  tags: string[]
  options: string[]
  sources: string[]
  currentGranay: Granary|null,
  llmModel: string
  embeddingModel: string
}

const granaryForm = ref<GranaryForm>({
  name: '',
  description: '',
  avatar: '',
  avatarCache: '',
  tags: [],
  options: [],
  sources: [],
  currentGranay: null,
  llmModel: '',
  embeddingModel: ''
})

const fileInput = ref<HTMLInputElement | null>(null)

const loadDocuments = async () => {
  console.log("doc load documents")
  if (granary.value != null) {
    console.log("doc load documents granary not null")
    granary.value.sources.forEach(async (source) => {
      console.log("doc load documents source", source)
      let req = {urn:source} as GetResourceRequest
      let res = await GetResource(req)
      documents.value.push(res)
    })
  }
}
const router = useRouter()
const route = useRoute()

const parseParamFromRoute = async () => {
  try {
      console.log("doc parse param")
      const urn = route.query.granary
      let reload = true
      console.log("doc granary urn:", urn)
      if (urn === null || urn === undefined) {
          granary.value = null
          reload = false
      } else if (granary.value != null) {
          if (granary.value.urn === urn) {
              console.log("no need to reload")
              reload = false
          }
      }

      if (reload) {
          console.log("doc reload granary")
          let req = {urn:urn} as GetGranaryRequest
          let res = await GetGranary(req)
          granary.value = res
      }

      userStore.granary = granary.value
      if (granary.value != null) {
        granaryForm.value.currentGranay = granary.value
        granaryForm.value.sources = granary.value.sources
        granaryForm.value.name = granary.value.name
        granaryForm.value.description = granary.value.description
        granaryForm.value.avatar = granary.value.avatar
        granaryForm.value.tags = granary.value.tags
        granaryForm.value.options = Object.entries(granary.value.options)
          .filter(([_, value]) => value === 'true')
          .map(([key]) => key)
        granaryForm.value.llmModel = granary.value.llmModel
        granaryForm.value.embeddingModel = granary.value.embeddingModel
        console.log("doc parse param granaryForm", granaryForm.value)
        
      }
  } catch (error) {
      console.error('Error parsing document from route:', error)
  }
}

const loadModels = () => {
  console.log("doc load models")
  const pageToken = { limit: 1000, offset: 0 }
  const filter = ""
  ListModels({ pageSize: 1000, pageToken, filter: filter }).then((res:ListLLMModelResponse)=>{
    res.models.forEach(model => {
      if (model.modelType == ModelType.CHAT) {
        llmModels.value.push(model)
      } else if (model.modelType == ModelType.EMBEDDING) {
        embeddingModels.value.push(model)
      }
    })
  }).catch(error => {
      console.error('Failed to fetch news:', error)
  })
}

const saveGranary = async () => {
  try {
    if (granary.value) {
      // Update existing granary
      let g={...granary.value}
      let updateMask=[]
      updateMask.push("name")
      if (g.name != granaryForm.value.name) {
        g.name = granaryForm.value.name
        updateMask.push("name")
      }

      if (g.description != granaryForm.value.description) {
        g.description = granaryForm.value.description
        updateMask.push("description")
      }

      if (g.avatar != granaryForm.value.avatarCache) {
        g.avatar = granaryForm.value.avatarCache
        updateMask.push("avatar") 
      }

      if (g.tags != granaryForm.value.tags) {
        g.tags = granaryForm.value.tags
        updateMask.push("tags")
      }

      if (g.llmModel != granaryForm.value.llmModel) {
        g.llmModel = granaryForm.value.llmModel
        updateMask.push("llm_model")
      }
      
      if (g.embeddingModel != granaryForm.value.embeddingModel) {
        g.embeddingModel = granaryForm.value.embeddingModel
        updateMask.push("embedding_model")
      }

      g.options =  Object.fromEntries(
          buildTypeOptions.map(option => [
            option.value,
            granaryForm.value.options.includes(option.value).toString()
          ])
      )
      updateMask.push("options")
      
      let req={granary:g, updateMask:updateMask} as UpdateGranaryRequest

      const res = await UpdateGranary(req)
      granary.value = res
      ElMessage.success('知识库更新成功')
    } else {
      // Create new granary
      const req = {
        name: granaryForm.value.name,
        description: granaryForm.value.description,
        avatar: granaryForm.value.avatar,
        tags: granaryForm.value.tags,
        llmModel: granaryForm.value.llmModel,
        embeddingModel: granaryForm.value.embeddingModel,
        options: Object.fromEntries(
          buildTypeOptions.map(option => [
            option.value,
            granaryForm.value.options.includes(option.value).toString()
          ])
        ),
      } as CreateGranaryRequest

      const res = await CreateGranary(req)
      granary.value = res
      ElMessage.success('知识库创建成功，请上传文档')
      userStore.granary = res
      await router.push(`/granary/config?granary=${res.urn}`)
      // window.location.reload()
    }
  } catch (error) {
    console.error('Error saving granary:', error)
    ElMessage.error('保存失败')
  }
}

const beforeAvatarUpload = (file: File) => {
  const isImage = file.type.startsWith('image/')
  const isLt2M = file.size / 1024 / 1024 < 2

  if (!isImage) {
    ElMessage.error('头像必须是图片格式!')
    return false
  }
  if (!isLt2M) {
    ElMessage.error('头像大小不能超过 2MB!')
    return false
  }
  return true
}

const handleAvatarUpload = async (options: any) => {
  try {
    const file = options.file

    const localUrl = URL.createObjectURL(file)
    granaryForm.value.avatar = localUrl // 立即更新预览

    let req = {filename: file.name, type: file.type} as CreateResourceRequest
    req.content = new Uint8Array(await file.arrayBuffer())
    let res = await CreateResource(req)

    granaryForm.value.avatarCache = getBaseUrl() + "/file/"+res.urn+"/"+file.name
    ElMessage.success('头像上传成功')
  } catch (error) {
    console.error('Error uploading avatar:', error)
    ElMessage.error('头像上传失败')
  }
}

const handleDelete = (urn: string) => {
  const index = granaryForm.value.sources.findIndex(item => item === urn)
  if (index !== -1) {
    granaryForm.value.sources.splice(index, 1)
  }
  documents.value = documents.value.filter(item => item.urn !== urn)
}

const handleStart = async () => {
  try {
    if (granary.value) {
      let req = {urn:granary.value.urn, cmd:GranaryCmd.START} as CtrlGranaryRequest
      let res = await CtrlGranary(req)
      console.log("start resource:", res)
      ElMessage.success('启动任务成功')
      userStore.granary = null
      const statusReq = {urn: granary.value!.urn} as GetGranaryRequest
      let  statusRes = await GetGranary(statusReq)
      granaryForm.value.currentGranay = statusRes
      granary.value = statusRes

      reloadGranaryStatus()      
    } else {
      ElMessage.error('请先创建知识库')
    }
  } catch (error) {
    console.error('启动失败:', error)
  }
}

const reloadGranaryStatus = async () => {
  if (granary.value == null) {
    return
  }
  const statusReq = {urn: granary.value!.urn} as GetGranaryRequest
  const intervalId = setInterval(async () => {
    try {  
      console.log("load building granary")
      let statusRes = await GetGranary(statusReq)
      if (granaryForm.value.currentGranay == null) {
        granaryForm.value.currentGranay = statusRes
      } else {
        granaryForm.value.currentGranay.status = statusRes.status
        granaryForm.value.currentGranay.summary = statusRes.summary
        granaryForm.value.currentGranay.tags = statusRes.tags
      }

      if (granary.value == null) {
        granary.value = statusRes
      } else {
        granary.value.status = statusRes.status
      }
      
      if (statusRes.status === GranaryStatus.ENDED || statusRes.status === GranaryStatus.FAILED || statusRes.status === GranaryStatus.STOPPED) {
        clearInterval(intervalId)
      }
      
    } catch (error) {
      console.error('Error checking status:', error)
      clearInterval(intervalId)
    }
  }, 5000) // 每5秒检查一次
}

const handleStop = async () => {
  try {
    if (granary.value) {
      let req = {urn:granary.value.urn, cmd:GranaryCmd.STOP} as CtrlGranaryRequest
      let res = await CtrlGranary(req)
      ElMessage.success('停止任务成功')
      userStore.granary = null
      window.location.reload()
    } else {
      ElMessage.error('请先创建知识库')
    }
  } catch (error) {
    console.error('停止失败:', error)
  }
}

const handleUpdate = async () => {
  try {
    if (granary.value) {
      let req = {urn:granary.value.urn, cmd:GranaryCmd.INCREMENTAL} as CtrlGranaryRequest
      let res = await CtrlGranary(req)
      ElMessage.success('更新任务已启动')
      userStore.granary = null
      const statusReq = {urn: granary.value!.urn} as GetGranaryRequest
      let  statusRes = await GetGranary(statusReq)
      granaryForm.value.currentGranay = statusRes
      granary.value = statusRes

      reloadGranaryStatus()      
    } else {
      ElMessage.error('请先创建知识库')
    }
  } catch (error) {
    console.error('更新失败:', error)
    ElMessage.error('更新失败')
  }
}

// Function to determine the tag type based on the status
const statusTagType = (status: GranaryStatus | undefined) => {
  if (status === undefined) {
      return 'info'
    }
    switch (status) {
      case GranaryStatus.CREATED:
        return 'primary'
      case GranaryStatus.ENDED:
        return 'success'
      case GranaryStatus.FAILED:
        return 'danger'
      case GranaryStatus.GRAPHING:
        return 'warning'
      case GranaryStatus.CHUNKING:
        return 'warning'
      case GranaryStatus.SUMMARIZING:
        return 'warning'
      default:
        return 'info'        
    }
}

onMounted(() => {
  console.log("doc on mounted")
  if (userStore.granary != null) {
    granary.value = userStore.granary
  }

  parseParamFromRoute().then(() => {
    loadDocuments()
    loadModels()
    reloadGranaryStatus()
  })
})

</script>

<style scoped lang="scss">
.document-container {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.top-section {
  display: flex;
  gap: 24px;
  min-height: 400px;
}

.info-panel {
  flex: 1;
  background: #fff;
  border-radius: 4px;
  border: 1px solid #e4e7ed;
  padding: 20px;
}

.form-content {
  margin-top: 20px;
}

.summary-section {
  margin-top: 20px;
}

.summary-header {
  margin-bottom: 16px;
  border-bottom: 1px solid #e4e7ed;
  padding-bottom: 8px;

  h3 {
    margin: 0;
    font-size: 16px;
    color: #303133;
  }
}

.summary-content {
  flex: 1;
  overflow-y: auto;
}

.summary-text {
  font-size: 14px;
  line-height: 1.6;
  color: #606266;
  white-space: pre-wrap;
}

.empty-summary {
  color: #909399;
  text-align: center;
  padding: 40px 0;
}

.bottom-section {
  background: #fff;
  border-radius: 4px;
  border: 1px solid #e4e7ed;
  padding: 20px;
}

.name-input {
  font-size: 20px;
  font-weight: bold;
  
  :deep(.el-input__inner) {
    border: none;
    padding: 0;
    
    &:focus {
      border: 1px solid #dcdfe6;
      padding: 0 8px;
    }
  }
}

.model-select {
  width: 100%;
}

.granary-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}

.granary-title {
  flex: 1;
  
  .el-form-item {
    margin-bottom: 0;
  }

  .name-input {
    margin-bottom: 0;
    
    :deep(.el-input__wrapper) {
      padding-top: 0;
      padding-bottom: 0;
    }
  }
}

.granary-tags {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;

  .tag {
    margin-right: 4px;
  }
}

.divider {
  height: 1px;
  background-color: #e4e7ed;
  margin: 16px 0;
}

.sub-description {
  margin: 8px 0 16px;
}

.search-bar {
  display: flex;
  gap: 16px;
  margin-bottom: 20px;
}

.add-button {
  white-space: nowrap;
}

.file-name {
  display: flex;
  align-items: center;
  gap: 8px;
}

.el-dropdown-link {
  cursor: pointer;
  margin-left: 12px;
}

.name-section, .description-section, .build-types {
  display: flex;
  align-items: flex-start;
  
  .label {
    color: #606266;
    width: 70px;
    flex-shrink: 0;
    text-align: left;
    white-space: nowrap;
  }
}

.name-section {
  .name-input {
    flex: 1;
  }
}

.description-section {
  .description-input {
    flex: 1;
  }
}

.build-types {
  align-items: center;
  
  .el-checkbox-group {
    flex: 1;
  }
}

.table-header {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-bottom: 16px;
}

.upload-btn {
  padding: 8px;
  height: auto;
  background: rgba(0, 0, 0, 0.04);
  border: none;
  
  &:hover {
    background: rgba(0, 0, 0, 0.08);
  }
}

.upload-icon {
  width: 20px;
  height: 20px;
  vertical-align: middle;
}

.delete-btn {
  margin-left: 12px;
  padding: 4px;
}

.delete-icon {
  width: 16px;
  height: 16px;
  vertical-align: middle;
}

.action-buttons {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}

.form-row {
  display: flex;
  align-items: center;
  gap: 20px;
}

.name-container {
  flex: 1;
  margin: 0;
}

.avatar-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 30px;
  height: 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;

  &:hover {
    border-color: var(--el-color-primary);
  }
}

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: block;
}

.default-avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 64px;
  height: 64px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.el-avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.full-width {
  width: 100%;
}

.full-width :deep(.el-input),
.full-width :deep(.el-select),
.full-width :deep(.el-textarea) {
  width: 100%;
}

.name-container {
  flex: 1;
}

.name-input {
  width: 100%;
}

.description-input {
  width: 100%;
}

.model-select {
  width: 100%;
}

.save-btn,
.control-btn {
  margin-left: 8px;
  padding: 8px;
  height: 32px;
  width: 32px;
}

.save-icon,
.control-icon {
  width: 16px;
  height: 16px;
}

.start-btn {
  &:hover {
    color: #67C23A;
    border-color: #67C23A;
  }
}

.stop-btn {
  &:hover {
    color: #F56C6C;
    border-color: #F56C6C;
  }
}

.update-btn {
  &:hover {
    color: #409EFF;
    border-color: #409EFF;
  }
}

.granary-status {
  margin-top: 16px;
}

.status-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.control-btn {
  margin: 0;
  padding: 8px;
  height: 32px;
  width: 32px;
}

.form-footer {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #e4e7ed;
}

.primary-button {
  background: #1677ff;
  border-color: #1677ff;
  
  &:hover {
    background: #4096ff;
    border-color: #4096ff;
  }
}

.no-sources-message {
  margin-top: 16px;
  text-align: center;
  color: #909399;

  .source-link {
    color: #1677ff;
    text-decoration: none;
    margin-left: 8px;
  }
}
</style>
